<?php
class CTpbPaymentOnline {
	public $client;
	public $error_code;
	public $err;
	public $user_name = 'vimua';
	public $password = 'vimua@123';

	const RESULT_SUCCESS															= '21001';		// Tài khoản hợp lệ
	const RESULT_ACCOUNT_NOT_EXIST										= '20001';		// Tài khoản không tồn tại
	const RESULT_ACOUNT_INVALID												= '20002';		// Tài khoản không hợp lệ
	const RESULT_ACOUNT_NOT_ENOUGH										= '20003';		// Tài khoản không đủ tiền
	const RESULT_INVALID_REQUEST											= '20004';		// Request message with invalid format
	const RESULT_VALID_ACCOUNT_SUCCESS_TRANSACTION		= '21101';		// Tài khoản hợp lệ, giao dịch thành công
	const RESULT_DOUBLICATE_INVOICE										= '20101';		// Đơn hàng trùng lặp
	const RESULT_TRANSACTION_FAILED										= '20102';		// Giao dịch thất bại
	const RESULT_TRANSACTION_SUCCESS									= '21201';		// Giao dịch hợp lệ, thực hiện thành công
	const RESULT_TRANSACTION_NOT_SUCCESS							= '20201';		// Giao dịch hợp lệ, thực hiện thành công


	function clearError() {
		$this->error_code = self::RESULT_SUCCESS;
		$this->err = '';
	}

	function setError($error_code, $error_desc) {
		$this->error_code = $error_code;
		$this->err = $error_desc;
	}

	function getError() {
		if ($this->error_code!=self::RESULT_SUCCESS)
			return $this->error_code . ': ' . $this->err;
		else
			return '';
	}

	/**
	 * Constructor
	 *
	 */
	function __construct() {
		require_once(ROOT_DIR.'3rdparty/nusoap/nusoap.php');
		require_once(ROOT_DIR.'lib/data/CXml.php');
		$this->client = new nusoap_client("http://payment.tpb.com.vn/Test/Test.asmx?wsdl", true);
		$this->err = $this->client->getError();
		if ($this->err) {
			echo '<h2>Constructor error</h2><pre>' . $this->err . '</pre>';
			echo '<h2>Debug</h2><pre>' . htmlspecialchars($this->client->getDebug(), ENT_QUOTES) . '</pre>';
			exit();
		}
	}

	function error($fault, $result) {
		if ($fault) {
			echo '<h2>Fault</h2><pre>'; print_r($result); echo '</pre>';
		} else {
			$this->err = $this->client->getError();
			if ($this->err) {
				echo '<h2>Error</h2><pre>', $this->err, '</pre>';
			} else {
				echo '<h2>Result</h2><pre>'; print_r($result); echo '</pre>';
			}
		}
		return $result;
	}

	function xmlFromArray($arr, $root = true) {
		if ($root) $xml = '<?xml version="1.0" ?><VIMUA>'; else $xml = '';
		if (!is_array($arr)) {
			$xml .= $arr;
		} else {
			foreach ($arr as $key=>$value) {
				$xml .= "<$key>".$this->xmlFromArray($value, false)."</$key>";
			}
		}
		if ($root) $xml .= '</VIMUA>';
		return $xml;
	}


	/**
	 * Validate
	 *
	 * @return bool true if account is validated
	 */
	function validateAccount($account, $id_card, $amount) {
		$this->clearError();
		$result = $this->client->call('processRequest', array(
			'xRefID'						=> 'vimua',
			'user'								=> $this->user_name,
			'password'						=> $this->password,
			'code'				=> 'VIMUA-AC',
			'message'		=> $this->xmlFromArray(array(
				'VA_VMTXN_REQ' => array(
					'TNXREF'					=> '101525555555',
					'TXNACC'					=> $account,
					'TXNIDCARD'				=> $id_card,
					'INVOICE_AMOUNT'	=> $amount,
					'TRANS_DATE'			=> date('YmdHis')
				)
			))
		));
		if (DEBUG==true) $this->result = $result;
		if (!isset($result) || !is_array($result)) {
			return false;
		} else {
			$result = CXml::xmlstring2array($result['processRequestResult']);
			if (!is_array($result)) return false;

			/*
						<?xml version="1.0" ?>
						<EBG>
							<VA_VMTXN_RESP>
								<RESP_CODE>00</RESP_CODE>					// Mã trả về
								<RESP_DESC>Success</RESP_DESC>		// Mô tả trả về
							<VA_VMTXN_RESP>
						</EBG>
			*/

			$response_code = @$result['VA_VMTXN_RESP']['RESP_CODE'];
			if (!isset($response_code)) return false;

			if ($response_code == self::RESULT_SUCCESS) {
				$this->err = '';
				return true;
			} else {
				$error_list = array(
					'01'=>'Không tìm thấy thông tin tài khoản',
					'02'=>'Tài khoản có số dư nhỏ hơn giá trị đơn hàng',
					'99'=>'Request sai định dạng',
				);
				$this->setError($result['VA_VMTXN_RESP']['RESP_CODE'], $result['VA_VMTXN_RESP']['RESP_DESC']);
				return false;
			}
		}
	}


	/**
	 * Enter description here...
	 *
	 * @param string $account
	 * @param string $id_card
	 * @param CTransactionDetail $transaction_detail
	 * @return array ('success'=>, 'trans_id' =>, 'invoice_no' =>, 'invoice_amount' =>, 'resp_desc' =>)
	 */
	function initTransaction($account, $id_card, $transaction_detail) {
		$this->clearError();
		$invoice = array();
		foreach ($transaction_detail->products as $product) {
			if (false) $product = new CTransactionProduct();
			$invoice[] = $this->xmlFromArray(array(
				'GOOD' => array(
					'GOOD_NAME'				=> $product->product_code,
					'GOOD_DESC'				=> $product->product_name,
					'GOOD_COST'				=> $product->product_price * 1000,
					'AMOUNT'					=> $product->product_quantity
				)
			), false);
		}

		$shipping_fee = $transaction_detail->shipping_fee - $transaction_detail->free_shipping;
		if ($shipping_fee > 0) {
			$invoice[] = $this->xmlFromArray(array(
				'GOOD' => array(
					'GOOD_NAME'				=> 'SHIPPING',
					'GOOD_DESC'				=> 'Phi van chuyen',
					'GOOD_COST'				=> $shipping_fee * 1000,
					'AMOUNT'					=> 1
				)
			), false);
		}

		$result = $this->client->call('processRequest', array(
			'xRefID'							=> 'vimua',
			'user'								=> $this->user_name,
			'password'						=> $this->password,
			'code'								=> 'VIMUA-CPIT',
			'message'							=> $this->xmlFromArray(array(
				'CPIT_VMTXN_REQ' => array(
					'TNXREF'					=> '101525555555',
					'TXNACC'					=> $account,
					'TXNIDCARD'				=> $id_card,
					'INVOICE_AMOUNT'	=> $transaction_detail->amount * 1000,
					'TRANS_DATE'			=> date('YmdHis'),
					'INVOICE_DTL'			=> join('', $invoice),
				)
			))
		));
		if (DEBUG==true) $this->result = $result;

		if (!isset($result) || !is_array($result)) {
			return array('success'=>false);
		} else {
			$result = CXml::xmlstring2array($result['processRequestResult']);
			if (!is_array($result)) return array('success'=>false);

			/*
						<?xml version="1.0" ?>
						<EBG>
							<CPIT_VMTXN_RESP>
								<RESP_CODE>00</RESP_CODE>										// Mã kết quả trả về
								<TRANS_ID>1234</TRANS_ID>										// Mã giao dịch trả về nếu thành công
								<INVOICE_NO>VM0123434</INVOICE_NO>					// Mã đơn hàng
								<INVOICE_AMOUNT>14300000</INVOICE_ AMOUNT>	// Số tiền đơn hàng
								<RESP_DESC>Success</RESP_DESC>							// Mô tả trả về
							</CPIT_VMTXN_RESP>
						</EBG>
			*/

			$response_code = @$result['CPIT_VMTXN_RESP']['RESP_CODE'];
			if (!isset($respons_code)) return array('success'=>false);

			if ($response_code == self::RESULT_SUCCESS) {
				if ($this->insertTransactionToDb($result)) {
					return array(
						'success'					=> true,
						'trans_id'				=> $result['CPIT_VMTXN_RESP']['TRANS_ID'],
						'invoice_no'			=> $result['CPIT_VMTXN_RESP']['INVOICE_NO'],
						'invoice_amount'	=> $result['CPIT_VMTXN_RESP']['INVOICE_AMOUNT'],
						'resp_desc'				=> $result['CPIT_VMTXN_RESP']['RESP_DESC']
					);
				} else {
					$this->setError('01', 'Không đưa được thông tin đơn hàng vào cơ sở dữ liệu');
					return array('success'=>false);
				}
			} else {
				$error_list = array(
					'03'=>'Đơn hàng trùng lặp',
				);
				$this->setError($result['VA_VMTXN_RESP']['RESP_CODE'], $result['VA_VMTXN_RESP']['RESP_DESC']);
				return false;
			}
		}
	}

	/**
	 * Validate
	 *
	 * @param string $account
	 * @param string $id_card
	 * @param double $amount
	 * @param string $trans_id
	 * @param string $trans_result
	 * @return bool true if account is validated
	 */
	function finishTransaction($account, $id_card, $amount, $trans_id, $trans_result) {
		$this->clearError();
		$result = $this->client->call('processRequest', array(
			'xRefID'							=> 'vimua',
			'user'								=> $this->user_name,
			'password'						=> $this->password,
			'code'				=> 'VIMUA-CPITS',
			'message'		=> $this->xmlFromArray(array(
				'CPITS_VMTXN_REQ' => array(
					'TNXREF'					=> '101525555555',
					'TXNACC'					=> $account,
					'TXNIDCARD'				=> $id_card,
					'INVOICE_AMOUNT'	=> $amount,
					'TRANS_DATE'			=> date('YmdHis'),
					'TRANS_RSL'				=> $trans_result
				)
			))
		));
		if (!isset($result) || !is_array($result)) {
			return false;
		} else {
			$result = CXml::xmlstring2array($result['processRequestResult']);
			if (!is_array($result)) return false;

			/*
					<?xml version="1.0" ?>
					<EBG>
						<CPITS_VMTXN_RESP>
							<INVOICE_NO>VM0123434</INVOICE_NO>
							<TRANS_ID>1234</TRANS_ID>
							<TRANS_RSL>VM0123434</TRANS_RSL>
							<INVOICE_AMOUNT>14300000</INVOICE_ AMOUNT>
							<RESP_CODE>00</RESP_CODE>						// Mã trả về
							<RESP_DESC> Success</RESP_DESC>			// Mô tả trả về
						<CPITS_VMTXN _RESP>
					</EBG>
			*/

			$response_code = @$result['CPITS_VMTXN_RESP']['RESP_CODE'];
			if (!isset($response_code)) return false;

			if ($response_code == self::RESULT_SUCCESS) {
				if ('Success' == $this->changeTransactionStatus($trans_id, $trans_result)) {
					$this->clearError();
					return true;
				} else {
					return false;
				}
			} else {
				$this->setError($result['CPITS_VMTXN_RESP']['RESP_CODE'], $result['CPITS_VMTXN_RESP']['RESP_DESC']);
				return false;
			}
		}
	}

	function insertTransactionToDb($transaction) {
		$transaction = $transaction['EBG']['CPIT_VMTXN_RESP'];
		$time = date('Y:m:d H:i:s');
		$newTransaction = array(
			'tt_trans_id'					=> $transaction['TRANS_ID'],
			'tt_invoice_no'				=> $transaction['INVOICE_NO'],
			'tt_payment_amount'		=> $transaction['INVOICE_AMOUNT'],
			'tt_status'						=> 0,
			'tt_created_time'			=> $time,
			'tt_modified_time'		=> $time
		);
		if (CTable('tpb_transaction')->insert($newTransaction)) {
			$newTransactionLog = array(
				'ttl_transaction'			=> $transaction['TRANS_ID'],
				'ttl_status'					=> 0,
				'tt_changeed_time'		=> $time,
				'tt_comment'					=> $transaction['RESP_DESC']
			);
			CTable('tpb_transaction_log')->insert($newTransactionLog);
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Change transaction status
	 *
	 * @param string $trans_id
	 * @param number $trans_status
	 * @param double $trans_amount check amount of transaction (-1 means no check)
	 * @param string $trans_comment
	 * @return string
	 * 		'InvalidTransaction', 'WrongAmount', 'Success'
	 */
	function changeTransactionStatus($trans_id, $trans_status, $trans_amount = -1, $trans_comment = '') {
		// Check whether transaction is exists?
		$transaction = CTable('tpb_transaction')->select(array('tt_trans_id'=>$trans_id));
		if (!isset($transaction) || !is_array($transaction)) {
			return 'InvalidTransaction';
		}

		if ($trans_amount!=-1) {
			if ($transaction['tt_payment_amount']) {
				return 'WrongAmount';
			}
		}

		$time = date('Y:m:d H:i:s');
		$newTransactionLog = array(
			'ttl_transaction'			=> $trans_id,
			'ttl_status'					=> $trans_status,
			'ttl_changed_time'		=> $time,
			'ttl_comment'					=> $trans_comment
		);
		CTable('tpb_transaction_log')->insert($newTransactionLog);
		return 'Success';
	}
}